﻿using System.Collections;
using System.Collections.Generic;
using System.Text;
using Protocol.SouthGridProtocol.Blocks;
using Protocol.SouthGridProtocol.Decoder;
using Protocol.SouthGridProtocol.Encoder;
using PacoToolKit.Format;
namespace Protocol.SouthGridProtocol.Model
{
    public class C0CH
    {
        private static string afn = "0C";
        private static string head = "68";
        private static string bottom = "16";
        private static Seq seq = new Seq(0, 1, 1, 1, 3);
        private static C c = new C(0, 1, 1, null, 0, 11);//prm=1,funcode=11

        /// <summary>
        /// di数据长度表(字节)
        /// </summary>
        private static Hashtable TerminalSpecialDiHaseTable = new Hashtable { 
            {"E1800001",2},{"E1800002",1},{"E1800003",1},{"E1800004",2},{"E1800005",2},
            {"E1800006",2},{"E1800007",2},{"E1800008",2},{"E1800009",16},{"E1800010",3},
            {"E1800011",2},{"E1800012",2},{"E1800013",3},{"E1800014",3},{"E1800015",1},
            {"E1800016",2},{"E1800017",2},{"E1800018",9},{"E1800019",2}
        };
        /// <summary>
        /// 组成下发查询的报文
        /// </summary>
        /// <param name="concentrator"></param>
        /// <param name="dataList"></param>
        /// <returns></returns>
        public static string EncodeC0CH(string concentrator, List<CData> dataList)
        {
            //主站启动的发送帧的MSA应为非零值,终端启动发送帧的MSA应为零，其主站响应帧的MSA也应为零
            concentrator = concentrator.Substring(0, 12) + "01";

            StringBuilder sb = new StringBuilder();
            foreach (CData data in dataList)
            {
                sb.Append(data.da); sb.Append(data.di);
            }
            StringBuilder msgsb = new StringBuilder();
            string length = BaseEncoder.CalcLength(c.encodeC() + concentrator + afn + seq.encodeSeqString() + sb.ToString());
            string cs = BaseEncoder.CalcCSCode(c.encodeC() + concentrator + afn + seq.encodeSeqString() + sb.ToString());
            return head + length + length + head + c.encodeC() + concentrator + afn + seq.encodeSeqString() + sb.ToString() + cs + bottom;
        }

        /// <summary>
        /// 根据报文解析C0CH的数据块内容到数据块列表
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static List<CData> DecodeC0CH(string msg)
        {
            List<CData> dataList = new List<CData>();
            string dataRemain = msg.Remove(0, 32);
            while (dataRemain.Length > 4)
            {
                string da = dataRemain.Substring(0, 4);
                string di = dataRemain.Substring(4, 8);
                int currentDataBlockLength;
                string currentDataBlock;

                #region 0001FF00
                if (Formater.ReverseHexString(di).Equals("0001FF00"))
                {
                    //费率数
                    int rateNum = int.Parse(Formater.HEXtoDEC(dataRemain.Substring(12, 2)));

                    currentDataBlockLength = 1 + 4 * (rateNum+1);
                    currentDataBlock = dataRemain.Substring(12, currentDataBlockLength * 2);
                    
                    //4费率
                    if (rateNum == 4)
                    {
                        dataList.Add(new CData()
                        {
                            da = da,
                            di = Formater.ReverseHexString("00010000"),
                            data = currentDataBlock.Substring(2, 8)
                        });
                        dataList.Add(new CData()
                        {
                            da = da,
                            di = Formater.ReverseHexString("00010100"),
                            data = currentDataBlock.Substring(10, 8)
                        });
                        dataList.Add(new CData()
                        {
                            da = da,
                            di = Formater.ReverseHexString("00010200"),
                            data = currentDataBlock.Substring(18, 8)
                        });
                        dataList.Add(new CData()
                        {
                            da = da,
                            di = Formater.ReverseHexString("00010300"),
                            data = currentDataBlock.Substring(26, 8)
                        });
                        dataList.Add(new CData()
                        {
                            da = da,
                            di = Formater.ReverseHexString("00010400"),
                            data = currentDataBlock.Substring(34, 8)
                        });
                    }
                    else if(rateNum==0)
                    {
                        dataList.Add(new CData()
                        {
                            da = da,
                            di = Formater.ReverseHexString("00010000"),
                            data = currentDataBlock.Substring(2, 8)
                        });
                    }
                    dataRemain = dataRemain.Remove(0, 4 + 8 + currentDataBlockLength * 2);
                }
                #endregion

                #region 0201FF00
                else if (Formater.ReverseHexString(di).Equals("0201FF00"))
                {
                    currentDataBlockLength = 2 * 9;
                    currentDataBlock = dataRemain.Substring(12, currentDataBlockLength * 2);
                    dataList.Add(new CData()
                    {
                        da = da,
                        di = Formater.ReverseHexString("02010100"),
                        data = currentDataBlock.Substring(0, 4)
                    });
                    dataList.Add(new CData()
                    {
                        da = da,
                        di = Formater.ReverseHexString("02010200"),
                        data = currentDataBlock.Substring(4, 4)
                    });
                    dataList.Add(new CData()
                    {
                        da = da,
                        di = Formater.ReverseHexString("02010300"),
                        data = currentDataBlock.Substring(8, 4)
                    });
                    dataRemain = dataRemain.Remove(0, 4 + 8 + currentDataBlockLength * 2);
                }
                #endregion

                #region 0202FF00
                else if (Formater.ReverseHexString(di).Equals("0202FF00"))
                {
                    currentDataBlockLength = 3 * 6;
                    currentDataBlock = dataRemain.Substring(12, currentDataBlockLength * 2);
                    dataList.Add(new CData()
                    {
                        da = da,
                        di = Formater.ReverseHexString("02020100"),
                        data = currentDataBlock.Substring(0, 6)
                    });
                    dataList.Add(new CData()
                    {
                        da = da,
                        di = Formater.ReverseHexString("02020200"),
                        data = currentDataBlock.Substring(6, 6)
                    });
                    dataList.Add(new CData()
                    {
                        da = da,
                        di = Formater.ReverseHexString("02020300"),
                        data = currentDataBlock.Substring(12, 6)
                    });
                    dataRemain = dataRemain.Remove(0, 4 + 8 + currentDataBlockLength * 2);
                }
                #endregion

                #region 0203FF00
                else if (Formater.ReverseHexString(di).Equals("0203FF00"))
                {
                    currentDataBlockLength = 3 * 4;
                    currentDataBlock = dataRemain.Substring(12, currentDataBlockLength * 2);
                    dataList.Add(new CData()
                    {
                        da = da,
                        di = Formater.ReverseHexString("02030000"),
                        data = currentDataBlock.Substring(0, 6)
                    });
                    dataList.Add(new CData()
                    {
                        da = da,
                        di = Formater.ReverseHexString("02030100"),
                        data = currentDataBlock.Substring(6, 6)
                    });
                    dataList.Add(new CData()
                    {
                        da = da,
                        di = Formater.ReverseHexString("02030200"),
                        data = currentDataBlock.Substring(12, 6)
                    });
                    dataList.Add(new CData()
                    {
                        da = da,
                        di = Formater.ReverseHexString("02030300"),
                        data = currentDataBlock.Substring(18, 6)
                    });
                    dataRemain = dataRemain.Remove(0, 4 + 8 + currentDataBlockLength * 2);
                }
                #endregion

                #region other
                else
                {
                    currentDataBlockLength = GetDataLength(Formater.ReverseHexString(di));
                    currentDataBlock = dataRemain.Substring(12, currentDataBlockLength * 2);
                    dataList.Add(new CData()
                    {
                        da = da,
                        di = di,
                        data = currentDataBlock
                    });
                    dataRemain = dataRemain.Remove(0, 4 + 8 + currentDataBlockLength * 2);
                }
                #endregion
            }
            return dataList;
        }

        public static List<CData> DecodeC0CHTerminalSpecial(string msg)
        {
            List<CData> dataList = new List<CData>();

            int msgLength = BaseDecoder.GetLength(msg);//字节数


            int dataRemainLen = (msgLength - 10) * 2;//初始 剩余未读数据长度
            string dataRemain = msg.Substring(32, dataRemainLen);//初始 剩余未读数据

            //循环读取块
            while (dataRemainLen >= 12)
            {
                string da = dataRemain.Substring(0, 4);
                string di = dataRemain.Substring(4, 8);
                //
                //todo 带FF的（比如多费率，数据块数据未做）
                int currentDataBlockLength = (int)TerminalSpecialDiHaseTable[Formater.ReverseHexString(di)];//如果结果为0，则是该di未被查询到
                if (currentDataBlockLength == 0)
                {
                    break;//结束读取
                }
                string data = dataRemain.Substring(12, currentDataBlockLength * 2);
                //
                dataList.Add(new CData { da = da, di = di, data = data });//读完一块，加入列表

                //重新计算剩余未读数据
                dataRemain = dataRemain.Remove(0, (4 + 8 + currentDataBlockLength * 2));
                dataRemainLen = dataRemain.Length;
            }

            return dataList;
        }

        /// <summary>
        /// 查询 当前数据di的数据域长度，单位字节，当查询结果为0，则说明没有查询到di
        /// </summary>
        /// <param name="diValue">高在前，低在后</param>
        public static int GetDataLength(string diValue)
        {
            int length = 0;
            string di3 = diValue.Substring(0, 2);
            string di2 = diValue.Substring(2, 2);
            string di1 = diValue.Substring(4, 2);
            string di0 = diValue.Substring(6, 2);
            if (di3.Equals("00") && di2 != "FF")
            {
                if (!di1.Equals("FF"))
                {
                    //读取电能值
                    return 4;
                }
            }
            if (di3.Equals("01") && di2 != "FF")
            {
                //最大需量及发生时间
                return 8;
            }
            if (di3.Equals("02") && di2.Equals("01"))
            {
                //电压
                return 2;
            }
            if (di3.Equals("02") && di2.Equals("02"))
            {
                //电流
                return 3;
            }
            if (di3.Equals("02") && (di2.Equals("03") || di2.Equals("04") || di2.Equals("05")))
            {
                //功率
                return 3;
            }
            if (di3.Equals("02") && di2.Equals("06"))
            {
                //总功率因数
                return 2;
            }
            if (di3.Equals("02") && di2.Equals("07"))
            {
                //相位基准值
                return 2;
            }
            if (di3.Equals("02") && di2.Equals("08"))
            {
                //电压波形失真度
                return 2;
            }
            if (di3.Equals("02") && di2.Equals("09"))
            {
                //电流波形失真度 
                return 2;
            }
            if (di3 == "02" && di2 == "80" && di1 == "00" && di0 == "01")
            {
                //零线电流
                return 3;
            }
            if (di3 == "02" && di2 == "80" && di1 == "00" && di0 == "02")
            {
                //电网频率
                return 2;
            }
            if (di3 == "02" && di2 == "80" && di1 == "00" && di0 == "03")
            {
                //一分钟有功平均功率
                return 3;
            }
            if (di3 == "02" && di2 == "80" && di1 == "00" && di0 == "04")
            {
                //当前有功需量 
                return 3;
            }
            if (di3 == "02" && di2 == "80" && di1 == "00" && di0 == "05")
            {
                //当前无功需量
                return 3;
            }
            if (di3 == "02" && di2 == "80" && di1 == "00" && di0 == "06")
            {
                //当前视在需量
                return 3;
            }
            if (di3 == "02" && di2 == "80" && di1 == "00" && di0 == "07")
            {
                //表内温度
                return 2;
            }
            if (di3 == "02" && di2 == "80" && di1 == "00" && di0 == "08")
            {
                //时钟电池电压
                return 2;
            }
            if (di3 == "02" && di2 == "80" && di1 == "00" && di0 == "09")
            {
                //停电抄表电池电压
                return 2;
            }
            if (di3 == "02" && di2 == "80" && di1 == "00" && di0 == "0A")
            {
                //内部电池工作时间
                return 4;
            }
            if (di3 == "02" && di2 == "80" && di1 == "01" && di0 == "01")
            {
                //A相短时闪变
                return 2;
            }
            if (di3 == "02" && di2 == "80" && di1 == "01" && di0 == "02")
            {
                //B相短时闪变
                return 2;
            }
            if (di3 == "02" && di2 == "80" && di1 == "01" && di0 == "03")
            {
                //C相短时闪变
                return 2;
            }
            if (di3 == "02" && di2 == "80" && di1 == "01" && di0 == "04")
            {
                //A相长时闪变
                return 2;
            }
            if (di3 == "02" && di2 == "80" && di1 == "01" && di0 == "05")
            {
                //B相长时闪变
                return 2;
            }
            if (di3 == "02" && di2 == "80" && di1 == "01" && di0 == "06")
            {
                //C相长时闪变
                return 2;
            }
            if (di3 == "02" && di2 == "80" && di1 == "01" && di0 == "07")
            {
                //电压正序分量
                return 3;
            }
            if (di3 == "02" && di2 == "80" && di1 == "01" && di0 == "08")
            {
                //电压负序分量
                return 3;
            }
            if (di3 == "02" && di2 == "80" && di1 == "01" && di0 == "09")
            {
                //电压零序分量
                return 3;
            }
            if (di3 == "02" && di2 == "80" && di1 == "01" && di0 == "0A")
            {
                //电压负序不平衡度
                return 2;
            }
            if (di3 == "02" && di2 == "80" && di1 == "01" && di0 == "0B")
            {
                //电流正序分量
                return 3;
            }
            if (di3 == "02" && di2 == "80" && di1 == "01" && di0 == "0C")
            {
                //电流负序分量
                return 3;
            }
            if (di3 == "02" && di2 == "80" && di1 == "01" && di0 == "0D")
            {
                //电流零序分量
                return 3;
            }
            if (di3 == "02" && di2 == "80" && di1 == "01" && di0 == "0E")
            {
                //电流负序不平衡度
                return 2;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "01")
            {
                //有功电能表起始读数
                return 4;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "02")
            {
                //无功电能表起始读数
                return 4;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "03")
            {
                //电表常数(有功) 
                return 3;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "04")
            {
                //电表常数(无功) 
                return 3;
            }
            if (di3 == "02" && (di2 == "0A" || di2 == "0B"))
            {
                //谐波含有量 
                return 2;
            }
            if (di3 == "04" && di2 == "00" && di1 == "01" && di0 == "01")
            {
                //日期及星期(其中0代表星期天)
                return 4;
            }
            if (di3 == "04" && di2 == "00" && di1 == "01" && di0 == "02")
            {
                //时间
                return 3;
            }
            if (di3 == "03" && di2 == "01" && di1 == "00" && di0 == "00")
            {
                //失压总次数,总累计时间
                return 18;
            }
            if (di3 == "03" && di2 == "0B" && di1 == "00" && di0 == "00")
            {
                //失流总次数,总累计时间
                return 18;
            }
            if (di3 == "03" && di2 == "0E" && di1 == "00" && di0 == "00")
            {
                //流反向总次数 ,总累计时间
                return 18;
            }
            if (di3 == "03" && di2 == "30" && di1 == "00" && di0 == "00")
            {
                //编程总次数 
                return 3;
            }
            if (di3 == "03" && di2 == "30" && di1 == "01" && di0 == "00")
            {
                //电表清零总次数 
                return 3;
            }
            if (di3 == "03" && di2 == "30" && di1 == "02" && di0 == "00")
            {
                //需量清零总次数 
                return 3;
            }
            if (di3 == "04")
            {
                //电表运行状态字
                if (di0.Equals("FF"))
                {
                    return 14;
                }
                else
                {
                    return 2;
                }
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "08")
            {
                //剩余金额
                return 4;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "10")
            {
                //电压合格率统计数据
                return 27;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "11")
            {
                //A相电压合格率统计数据
                return 27;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "12")
            {
                //B相电压合格率统计数据
                return 27;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "13")
            {
                //C相电压合格率统计数据
                return 27;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "14")
            {
                //A相电流极值统计数据
                return 14;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "15")
            {
                //B相电流极值统计数据
                return 14;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "16")
            {
                //C相电流极值统计数据
                return 14;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "17")
            {
                //零序电流极值统计数据
                return 14;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "18")
            {
                //有功功率极值统计数据
                return 14;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "19")
            {
                //无功功率极值统计数据
                return 14;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "1A")
            {
                //功率因数极值统计数据
                return 12;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "1B")
            {
                //电流不平衡越限统计数据
                return 9;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "1C")
            {
                //电压不平衡度越限统计数据
                return 9;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "20")
            {
                //日停电总次数
                return 3;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "21")
            {
                //日停电总时间
                return 3;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "30")
            {
                //断相数据
                return 72;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "31")
            {
                //失压数据
                return 40;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && di0 == "32")
            {
                //失流数据
                return 40;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "00" && (di0 == "40" || di0 == "41" || di0 == "42" || di0 == "43" || di0 == "44" || di0 == "45"))
            {
                //电压波动值
                return 3;
            }

            if (di3 == "E1" && di2 == "00" && (di1 == "01" || di1 == "02" || di1 == "03") && di0 == "01")
            {
                //A相电压偏差最大值,最小值，平均值
                return 2;
            }
            if (di3 == "E1" && di2 == "00" && (di1 == "01" || di1 == "02" || di1 == "03") && di0 == "02")
            {
                //B相电压偏差最大值,最小值，平均值
                return 2;
            }
            if (di3 == "E1" && di2 == "00" && (di1 == "01" || di1 == "02" || di1 == "03") && di0 == "03")
            {
                //C 相电压偏差最大值,最小值，平均值
                return 2;
            }
            if (di3 == "E1" && di2 == "00" && (di1 == "01" || di1 == "02" || di1 == "03") && di0 == "04")
            {
                //频率偏差最大值,最小值，平均值
                return 1;
            }
            if (di3 == "E1" && di2 == "00" && (di1 == "01" || di1 == "02" || di1 == "03") && di0 == "05")
            {
                //电压不平衡度最大值,最小值，平均值
                return 2;
            }
            if (di3 == "E1" && di2 == "00" && (di1 == "01" || di1 == "02" || di1 == "03") && (di0 == "06" || di0 == "07" || di0 == "08" || di0 == "09" || di0 == "0A" || di0 == "0B" || di0 == "0C"))
            {
                //电压最大值 ,电流最大值,最小值，平均值
                return 2;
            }
            if (di3 == "E1" && di2 == "00" && (di1 == "01" || di1 == "02" || di1 == "03") && di0 == "0D")
            {
                //短时闪变最大值,最小值，平均值
                return 1;
            }
            if (di3 == "E1" && di2 == "00" && (di1 == "01" || di1 == "02" || di1 == "03") && di0 == "0E")
            {
                //长时闪变最大值,最小值，平均值
                return 1;
            }
            if (di3 == "E1" && di2 == "00" && (di1 == "01" || di1 == "02" || di1 == "03") && di0 == "0F")
            {
                //电压总畸变率最大值,最小值，平均值
                return 2;
            }
            if (di3 == "E1" && di2 == "00" && (di1 == "01" || di1 == "02" || di1 == "03") && di0 == "10")
            {
                //电流总畸变率最大值,最小值，平均值
                return 2;
            }

            if (di3 == "03" && di2 == "10" && (di1 == "00" || di1 == "01" || di1 == "02" || di1 == "03") && di0 == "00")
            {
                //电压合格率统计数据
                return 27;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "40" && (di0 == "14" || di0 == "15" || di0 == "16" || di0 == "17" || di0 == "18" || di0 == "19"))
            {
                //电流,功率极值统计数据
                return 14;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "40" && di0 == "1A")
            {
                //(本月) 功率因数极值统计数据
                return 12;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "40" && (di0 == "1B" || di0 == "1C"))
            {
                //(本月)电流,电压不平衡度越限统计数据
                return 9;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "40" && (di0 == "20" || di0 == "21"))
            {
                //(本月)停电总次数,停电总时间
                return 3;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "40" && di0 == "30")
            {
                //(本月)断相数据
                return 72;
            }
            if (di3 == "E1" && di2 == "00" && di1 == "40" && (di0 == "31" || di0 == "32"))
            {
                //(本月)失压数据,(本月)失流数据
                return 40;
            }
            return length;

        }
    }
}
